;***********************************************************
;*                                                         *
;*        Coleco ADAM Serial/Parallel Interface 6801       *
;*            source regenerated by Chris Braymen          *
;*           minor additions by Richard F. Drushel         *
;*                                                         *
;*  Note:  currently missing 59 bytes of STATUS routines,  *
;*  so the code is probably unusable as it now exists.     *
;*                                                         *
;***********************************************************
									    
		org     $F800

;***********************************************************
;* 6801 port registers
;***********************************************************

P1_DIR          EQU     $0000
P2_DIR          EQU     $0001
P1_DATA         EQU     $0002
P2_DATA         EQU     $0003
P3_DIR          EQU     $0004
P4_DIR          EQU     $0005
P3_DATA         EQU     $0006
P4_DATA         EQU     $0007
T_CNTLSTAT      EQU     $0008
RAM_CNTL        EQU     $0014

;***********************************************************
;* 6801 serial port registers
;***********************************************************

SCI_RM          EQU     10H             ;rate and mode
SCI_TR_CS       EQU     11H             ;xmit control and status
SCI_RX          EQU     12H             ;serial receive register
SCI_TX          EQU     13H             ;serial transmit register

ORFE            EQU     40H             ;overflow error bit
TDRE_MASK       EQU     20H             ;ready to xmit bit

;**********************************************************
;* Serial port states
;**********************************************************

CNTRL           EQU     00H
LENGTH_HI       EQU     01H
LENGTH_LO       EQU     02H
DATAIN          EQU     03H
CS_IN           EQU     04H
CMD_IN          EQU     05H
CMD_DATA_IN     EQU     06H

;**********************************************************
;* Centronics port states
;**********************************************************

LENGTH_HI_D       EQU     07H
LENGTH_LO_D       EQU     08H
DATAIN_D          EQU     09H
CS_IN_D           EQU     0AH

;**********************************************************
;* SmartWriter intercept states
;**********************************************************

LENGTH_HI_2       EQU     0BH
LENGTH_LO_2       EQU     0CH
DATAIN_2          EQU     0DH
CS_IN_2           EQU     0EH

E_ADDRESS     EQU     0EH                     ;our network addresses
D_ADDRESS     EQU     0DH
2_ADDRESS     EQU     02H

MN_RESET        EQU     00H*16
MN_STATUS       EQU     01H*16
MN_ACK          EQU     02H*16
MN_CLR          EQU     03H*16
MN_RECEIVE      EQU     04H*16
MN_CANCEL       EQU     05H*16
MN_SEND         EQU     06H*16
MN_NACK         EQU     07H*16
MN_READY        EQU     0DH*16

NM_STATUS       EQU     08H*16
NM_ACK          EQU     09H*16
NM_CANCEL       EQU     0AH*16
NM_SEND         EQU     0BH*16
NM_NACK         EQU     0CH*16

;***************************************************************
;* 2651 Uart IO addresses
;* Partially decoded, appears also at 0104, 0108, and 010C because
;* address lines 2 and 3 are not decoded.
;***************************************************************

UART_DATA       EQU     0100H
UART_STATUS     EQU     0101H
UART_MODE       EQU     0102H
UART_COMMAND    EQU     0103H

UART_TX_RDY     EQU     $01
UART_RX_RDY     EQU     $02


;***************************************************************
;* Protocol defines
;***************************************************************

XON_CHAR        EQU     $13     ;DC3, ^S
XOFF_CHAR       EQU     $11     ;DC1, ^Q

;***************************************************************
;* Serial port status bits
;***************************************************************

SS_CMD_AVAIL    EQU     $01     ;UART command available
SS_BYTE_AVAIL   EQU     $02     ;byte available to xmit to remote
SS_HI_WATER     EQU     $04     ;receive buffer full
SS_RX_RDY       EQU     $08     ;OK for UART to receive data
SS_SENT_XOFF    EQU     $10     ;we sent an XOFF to the remote
SS_SENT_XON     EQU     $20     ;we sent an XON to the remote
SS_GOT_XOFF     EQU     $40     ;we received an XOFF from the remote

;***************************************************************
;* Printer port status defines
;***************************************************************

SW_GOT_VTAB     EQU     $01     ;flag for making 2 vtabs into a LF
SW_GOT_BS       EQU     $02     ;flag for tracking backspaces
PP_BYTE_AVAIL   EQU     $10     ;byte available for parallel printer
SW_BYTE_AVAIL   EQU     $40     ;byte available for smartWriter
SW_REV_ON       EQU     $80     ;reverse printing is occuring

;***************************************************************
;* External memory and centronics port are enabled at 0110-01FF
;***************************************************************

;***************************************************************
;* Port 1
;*      Bit 0           ;DataStrobe output for parallel printer
;*      Bit 1           ;~DSR input
;*      Bit 2           ;~CTS input
;*
;*      Bit 3           ;Paper Out              ;Order ?
;*      Bit 4           ;Select Printer         ;?
;*      Bit 5           ;Busy                   ;?
;*
;*      Bit 6           ;~Serial printer select
;*      Bit 7           ;~Smartwriter select - disables SPI intercept
;***************************************************************

;***************************************************************
;* Start up code
;***************************************************************

		select  6800
		type    6803

START           equ     $               ;Reset brings us here
		SEI
		LDS     #STACK          ;init stack pointer

		CLRA
		STAA    P1_DATA         ;$0002 - clear reg
		LDAA    #$0001          ;all inputs except bit 0 output
		STAA    P1_DIR          ;$0000

		LDAA    #$0010          ;port 2 all inputs except bit 4
		STAA    P2_DIR          ;$0001

		LDAA    #$00FF          ;port 3 all outputs
		STAA    P3_DIR          ;$0004

		LDAA    #$00FF          ;port 4 all outputs
		STAA    P4_DIR          ;$0005

		LDAA    #$00FF          ;enable internal ram
		STAA    RAM_CNTL        ;$0014

;clear all of our ram

		LDX     #$01FF          ;top of external RAM
		CLRA
CLRRAM          equ     $               ;Clear ram loop
		STAA    $0000,X
		DEX
		CPX     #$007F          ;bottom of internal ram?
		BNE     CLRRAM          ;Clear ram loop

;read RS232 setup defaults into Ram locations

		LDD     DEF_TBL         ;baud, char length
		STD     BAUD_RATE
		LDD     DEF_TBL+2       ;parity, stop bits
		STD     PARITY
		LDD     DEF_TBL+4       ;protocol and DTR state
		STD     PROTOCOL
		LDAA    ROM_CHAR_MODE   ;default net send type
		STAA    CHAR_MODE_FLAG

		CLRA                    ;disable timer
		STAA    T_CNTLSTAT      ;$0008

		LDAA    #$0004          ;select internal clock
		STAA    SCI_RM          ;$0010

		LDAA    #$001A          ;Rx int enable,Rx enable,Tx enable
		STAA    SCI_TR_CS       ;$0011

;init RS232 receive buffer

		LDX     #BUFFER         ;#$008D
		STX     BUF_FILL_PTR    ;$0087
		STX     BUF_EMPTY_PTR   ;$0089

		LDX     #BUFFER_2       ;#$0116
		STX     BUF2_FILL_PTR   ;$0110
		STX     BUF2_EMPTY_PTR  ;$0112

		LDAA    #$0001          ;init column number to 1
		STAA    COLUMN_NUMBER

;copy status message to ram

		LDD     STAT_MSG_TBL_E
		STD     RAM_STAT_MSG_E          ;$00ED
		LDD     STAT_MSG_TBL_E + 2
		STD     RAM_STAT_MSG_E + 2      ;$00EF
		JSR     INIT_UART

;******************************************************************
;* Main loop
;******************************************************************

MAIN_LOOP       JSR     MANAGE_PRINTERS
		CLI                     ;allow adamnet interrupts
		LDAA    UART_STATUS
		BITA    #UART_RX_RDY    ;#$0002 any UART bytes coming in?
		BEQ     MAIN_00         ;no....so what?

MAIN_00         LDAA    BUF_COUNT       ;$008C - get # bytes in buffer
		CMPA    #$000A
		BPL     HI_WATER                ;if >= 0AH (10) then skip
		SEI                             ;no interrupts
		LDAB    RAM_STAT_MSG_E+5        ;$00F2
		ORAB    #SS_RX_RDY              ;#$0008 set bit 3
		ANDB    ~(#SS_HI_WATER+#SS_SENT_XOFF) ;#$00EB reset bits 4 and 2
		STAB    RAM_STAT_MSG_E+5        ;$00F2
		BRA     MAIN_0

HI_WATER        CMPA    #$004B
		BMI     MAIN_0                  ;if <= 4BH (75) then skip
		SEI                             ;no interrupts
		LDAA    RAM_STAT_MSG_E+5        ;$00F2
		ORAA    #SS_HI_WATER            ;#$0004 set bit 2
		ANDA    ~(#SS_SENT_XON+#SS_RX_RDY) ;#$00D7 reset bit 5 and 3
		STAA    RAM_STAT_MSG_E+5        ;$00F2

MAIN_0          CLI                             ;enable interrupts
		LDAB    CMD_SHADOW              ;get current cmd reg val
		JSR     GET_RTS                 ;get proper RTS bit
		STAB    UART_COMMAND            ;tell UART
		STAB    CMD_SHADOW              ;and save new shadow

		CLI                             ;enable ints again (?)
		LDAA    RAM_STAT_MSG_E+5        ;$00F2
		BITA    #SS_CMD_AVAIL           ;#$0001 is bit 0 set?
		BEQ     UART_MGR                ;no, go manage UART
		JSR     INIT_UART               ;yes-reprogram UART
LOOP_END        JMP     MAIN_LOOP               ;loop

UART_MGR        TAB                             ;get status in B
		ANDB    #SS_HI_WATER+SS_RX_RDY  ;#$000C are bits 2 or 3 set?
		BNE     DO_XONXOFF              ;yes-skip

CHK_SEND        LDAA    RAM_STAT_MSG_E+5        ;get status msg in A
		BITA    #SS_BYTE_AVAIL          ;#$0002 is bit 1 set?
		BEQ     LOOP_END                ;no, all done, skip back
		BSR     SEND_UART_DATA          ;yes-go send data
		BRA     LOOP_END                ;all done, skip back

SEND_UART_DATA  CLI                             ;enable ints
		LDAA    PROTOCOL                ;get the current protocol
		ANDA    #$0003                  ;is it RTS/CTS? (0)
		BNE     NOT_RTS                 ;no-skip
		LDAA    P1_DATA                 ;yes, get DSR and RTS
		ANDA    #$0006                  ;are both low?
		BEQ     SEND_IT                 ;yes, so send the UART byte
COMM_DONE       RTS

NOT_RTS         BITA    #$0001                  ;is it XON/XOFF?
		BEQ     SEND_IT                 ;no, no protocol, just do it
		LDAB    RAM_STAT_MSG_E+5        ;get status msg
		BITB    #SS_GOT_XOFF            ;#$0040 is bit 6 set? (wait for XON)
		BNE     COMM_DONE               ;yes, just returns...

SEND_IT         LDAA    U_XMIT_BUF           ;$00F3 - get buffered byte
		JSR     XMIT_UART            ;send it
		SEI                          ;disable ints
		LDAA    RAM_STAT_MSG_E+5     ;$00F2
		ANDA    ~#SS_BYTE_AVAIL      ;#$00FD reset bit 1
		STAA    RAM_STAT_MSG_E+5     ;$00F2
		RTS

DO_XONXOFF      LDAA    PROTOCOL                ;get current protocol
		BITA    #$0001                  ;is it XON/XOFF?
		BEQ     CHK_SEND                ;no, jump back to normal
		LDAA    RAM_STAT_MSG_E+5        ;$00F2 - get status msg
		BITA    #SS_HI_WATER            ;#$0004 is bit 2 set?  (HiWater)
		BEQ     DO_XON                  ;no-skip
		BITA    #SS_SENT_XOFF           ;#$0010 is bit 4 set? (wait to send XON)
		BNE     DO_XON                  ;yes-skip (don't send another XOFF!)
		LDAA    #XOFF_CHAR              ;#$0013
		JSR     XMIT_UART               ;send XOFF to remote
		SEI                             ;disable ints
		LDAA    RAM_STAT_MSG_E+5        ;$00F2 - get status msg
		ORAA    #SS_SENT_XOFF+#SS_HI_WATER ;#$0014 set bits 4 and 2
		ANDA    ~(#SS_SENT_XON+#SS_RX_RDY) ;#$00D7 reset bits 5 and 3
		STAA    RAM_STAT_MSG_E+5        ;$00F2
		BRA     CHK_SEND

DO_XON          LDAA    RAM_STAT_MSG_E+5        ;$00F2-get status msg
		BITA    #SS_RX_RDY              ;#$0008 is bit 3 set?
		BEQ     CHK_SEND                ;no-skip back to normal
		BITA    #SS_SENT_XON            ;#$0020 is bit 5 set? (sent XON)
		BNE     CHK_SEND                ;yes-skip (don't send another XON!)
		LDAA    #XON_CHAR               ;#$0011
		JSR     XMIT_UART               ;send XON to remote
		SEI                             ;disable ints
		LDAA    RAM_STAT_MSG_E+5        ;$00F2
		ORAA    #SS_SENT_XON+#SS_RX_RDY ;#$0028 set bits 5 and 3
		ANDA    ~(#SS_SENT_XOFF+#SS_HI_WATER) ;#$00EB reset bits 4 and 2
		STAA    RAM_STAT_MSG_E+5        ;$00F2
		JMP     CHK_SEND

;****************************************************************
;* XMIT_UART
;****************************************************************

XMIT_UART       CLI                     ;enable ints
		LDAB    UART_STATUS     ;get UART status
		BITB    #UART_TX_RDY    ;#$0001 is it ready for a byte?
		BEQ     XMIT_UART       ;no-loop until it is
		STAA    UART_DATA       ;send data to UART
		RTS

;****************************************************************
;* RCV_UART
;****************************************************************

RCV_UART        LDX     BUF_FILL_PTR    ;$0087 - get fill ptr
		LDAA    UART_DATA       ;$0100 - get the char
		LDAB    BUF_COUNT       ;$008C - get buffer count
		INCB                    ;inc it
		CMPB    #BUF_SIZE       ;#$005A buffer overflow?
		BEQ     RX_BUF_FULL     ;$0F yes-skip
		STAB    BUF_COUNT       ;$008C no-store new buffer count
		STAA    X,0             ;store serial byte in buffer
		INX                     ;inc buffer ptr
		CPX     #BUF_END        ;$00E7 at end of buffer?
		BNE     RX_BUF_OK       ;$03 no-skip
		LDX     #BUFFER         ;#$008D yes-reset buffer ptr to top
RX_BUF_OK       STX     BUF_FILL_PTR    ;$0087 - save new fill ptr
RX_BUF_FULL     SEI                     ;disable ints
		LDAB    RAM_STAT_MSG_E+5 ;$F2 - get status in B
		CMPA    #XOFF_CHAR      ;#$13 - is it XOFF?
		BNE     RX_NOT_XOFF     ;$04 no-skip
		ORAB    #SS_GOT_XOFF    ;#$40 - set got xoff bit
		BRA     RX_COMMON       ;$06 skip out
RX_NOT_XOFF     CMPA    #XON_CHAR       ;#$11 - is it XON?
		BNE     RX_COMMON       ;$02 no-skip
		ANDB    ~#SS_GOT_XOFF   ;#$BF - reset xoff bit
RX_COMMON       STAB    RAM_STAT_MSG_E+5 ;$F2 - save new status
		CLI                     ;enable ints
		RTS                     ;return

;******************************************************************
;* program the Uart's mode registers
;******************************************************************

INIT_UART       SEI                          ;disable ints
		LDAA    RAM_STAT_MSG_E+5     ;$00F2
		ANDA    ~#SS_CMD_AVAIL       ;#$00FE reset bit 0
		STAA    RAM_STAT_MSG_E+5     ;$00F2
		CLI                          ;enable ints

		LDAA    UART_COMMAND         ;resets mode sequencer
		LDAA    STOP_BITS            ;$0083 0=1sb, 1=2sb
		ASLA                         ;shift left
		INCA                         ;low bit is always set
		ASLA                         ;make room for parity
		ASLA

		LDX     #PARITY_TBL           ;get parity table base
		LDAB    PARITY                ;get par code 0=E,1=O,2=N
		ABX                           ;index into table
		LDAB    $0000,X               ;get UART bit code in B
		SEI                           ;disable ints
		STAB    TMP_PARITY            ;$00F8 save it in order to OR
		ORAA    TMP_PARITY            ;$00F8 mix parity with mode1 byte
		CLI                           ;enable ints

		ASLA                    ;make room for char len
		ASLA
		ORAA    CHAR_LEN        ;0=5,1=6,2=7,3=8

		ASLA                    ;make room for baud clock
		ASLA
		ORAA    #$0002          ;set asynch 16X baud clock
		STAA    UART_MODE       ;write mode 1 to UART

		LDAA    #$0030          ;set up internal clocks
		ORAA    BAUD_RATE       ;mix in baud rate
		STAA    UART_MODE       ;program mode 2

		LDAB    CMD_SHADOW      ;get command shadow
		ORAB    #$0005          ;enable RX and TX
		BSR     GET_DTR         ;update DTR and RTS bits
		STAB    UART_COMMAND    ;send command to UART
		STAB    CMD_SHADOW      ;and save cmd shadow
		RTS

;*********************************************************************
;* GET_DTR - Sets the proper bits in the UART command byte passed
;*           in B if the DTR state has changed.  Also handles
;*           the "Clear receive buffer" command
;*********************************************************************

GET_DTR         LDAA    DTR_STATE
		BITA    #$0080          ;if this is a new DTR command
		BEQ     NEW_DTR_CMD     ;then go process it
		RTS                     ;else just ret

NEW_DTR_CMD     ORAA    #$0080          ;set "old command" bit
		STAA    DTR_STATE       ;and save it back
		ANDA    #$0003          ;Anything set in lower 2 bits?
		BNE     FORCE_DTR       ;yes-skip

		;no-then we received a "clear receive buffer" cmd
		SEI                             ;disable ints
		LDAA    RAM_STAT_MSG_E+5        ;$00F2
		ANDA    ~(#SS_SENT_XON+#SS_SENT_XOFF+
			  #SS_RX_RDY+#SS_HI_WATER) ;#$00C3 reset bits 5,4,3,2
		STAA    RAM_STAT_MSG_E+5        ;$00F2
		CLR     BUF_COUNT               ;zero out the buffer count
		LDX     #BUFFER                 ;get buffer address
		STX     BUF_FILL_PTR             ;stash it in both ptrs
		STX     BUF_EMPTY_PTR
		CLI                             ;enable ints
		RTS

FORCE_DTR       BITA    #$0001          ;if bit 0 is set
		BNE     DTR_EXIT        ;then skip to force DTR low
		ANDB    #$00FD          ;else force DTR high
		BRA     GET_RTS         ;and go do RTS
DTR_EXIT        ORAB    #$0002          ;Force DTR low

;************************************************************
;* GET_RTS - sets the RTS bit in the UART cmd register value
;* passed in B
;* We get here wth B = CMD_SHADOW
;* What we return in B will get stuffed in the UART's
;* command register and saved in CMD_SHADOW
;************************************************************

GET_RTS         LDAA    PROTOCOL             ;get current xfer protocol
		BNE     RTS_EXIT             ;if it is not RTS/CTS skip
		LDAA    RAM_STAT_MSG_E+5     ;$00F2
		BITA    #SS_RX_RDY           ;#$0008 is bit 3 set?
		BNE     RTS_EXIT             ;yes-skip
		ANDB    #$00DF               ;Force RTS high
		RTS

RTS_EXIT        ORAB    #$0020               ;Force RTS low
		RTS

;**********************************************************************
;* This table provides the proper parity values for the 2651 when
;* indexed by the Adam's parity code.  This value must then be
;* shifted to bits 4 and 5 and merged with other information before
;* being shipped to the 2651 mode 1 register.
;**********************************************************************

PARITY_TBL      db      $03     ;even
		db      $01     ;odd
		db      $00     ;none

;Table of startup defaults for baud and format

DEF_TBL         equ     $
		db      $0A     ;baud rate 2400 baud
		db      $03     ;8 bit char
		db      $02     ;Code for no parity
		db      $00     ;Code for 1 stop bit
		db      $02     ;no protocol
		db      $01     ;DTR on
ROM_CHAR_MODE   db      $00     ;default to multi-byte transmissions
				;1 for single char transactions

;*******************************************************************
;* MANAGE_PRINTERS
;*******************************************************************

MANAGE_PRINTERS CLI                     ;enable interrupts
		LDAB    DEV2D_STATUS    ;$00FE - get printer status
		BITB    #PP_BYTE_AVAIL  ;#$0010 is parallel byte ready?
		BEQ     NO_PAR_BYTE_RDY ;no-skip
		JMP     DO_PARALLEL     ;yes-go process the char

NO_PAR_BYTE_RDY LDAA    BUF_2_COUNT     ;$0114 - get SW buffer count
		BNE     DO_SW_BUFFER    ;if chars in BUFFER2 then skip
		SEI                     ;else disable ints
		LDAA    DEV2D_STATUS    ;$00FE - get printer status
		ANDA    ~(#SW_BYTE_AVAIL+#$20) ;#$009F reset bits 5 and 6
		STAA    DEV2D_STATUS    ;$00FE - save new status
		CLI                     ;enable ints
RET_NOW         RTS

;*********************************************************************
;* DO_SW_BUFFER - process chars from the SmartWriter buffer
;*                ;Status is in B
;*********************************************************************

DO_SW_BUFFER    LDX     BUF2_EMPTY_PTR   ;$0112 - get buffer empty ptr
		BITB    #SW_GOT_VTAB     ;#$0001 got a vtab before?
		BNE     SW_2ND_VTAB      ;yes-jump

		BITB    #SW_GOT_BS       ;#$0002 got BS before?
		BNE     SW_2ND_BS        ;yes-jump

		BITB    #SW_BYTE_AVAIL   ;#$0040 any new chars in buffer?
		BEQ     RET_NOW          ;no-just return

		JSR     SCAN_FOR_CNTRL   ;look for a control char in buffer
		BCS     RET_NOW          ;carry set, none found, just return
		LDAB    DEV2D_STATUS     ;$00FE - get printer status
		BITB    #SW_REV_ON       ;#$0080 is reverse printing on?
		BEQ     SW_FORWARD       ;no - print line fwd
		JMP     SW_REVERSE       ;yup, print line reversed

SW_2ND_VTAB     LDAA    $0000,X         ;get char from buffer
		CMPA    #$000B          ;is it VT 1/2 line feed?
		BNE     NOT_VTAB        ;no-skip
		LDAA    #$000A          ;yes-replace with full LF
		STAA    $0000,X
		JSR     SERIAL_PRINTER  ;print the char
		SEI                     ;disable ints
		LDAB    DEV2D_STATUS    ;$00FE - get printer status
		ANDB    ~(#SW_GOT_VTAB+#SW_GOT_BS)  ;#$00FC reset bits 0 and 1
		JMP     DONE_BUF_CHR    ;finish up

NOT_VTAB        SEI                     ;disable ints
		LDAB    DEV2D_STATUS    ;$00FE - get printer status
		ANDB    ~(#SW_GOT_VTAB+#SW_GOT_BS)  ;#$00FC reset bits 0 and 1
		JMP     DONE_NO_BUF     ;just save status and exit

SW_2ND_BS       LDAA    $0000,X         ;get char from buffer
		CMPA    #$0008          ;is it BS backspace?
		BNE     NOT_BS          ;no-skip
		INC     BS_COUNT        ;inc the backspace count
		SEI                     ;disable ints
		LDAB    DEV2D_STATUS    ;$00FE - get printer status
		JMP     DONE_BUF_CHR    ;finish up

NOT_BS          LDAA    COLUMN_NUMBER   ;get column number
		INC     BS_COUNT        ;inc back space count
		LDAB    BS_COUNT
		CBA                     ;compare A and B
		BHI     COLUMN_OK       ;if column# >= backspaces then jump
		LDAA    #$0001          ;make column # 1
		BRA     COLUMN_RESET    ;skip

COLUMN_OK       SBA                     ;subtract backspaces from column#
COLUMN_RESET    STAA    COLUMN_NUMBER   ;save..
		CLR     BS_COUNT        ;clear the backspace count
		BRA     NOT_VTAB

;*****************************************************************
;* SW_FORWARD
;*****************************************************************

SW_FORWARD      JSR     SCAN_FOR_CNTRL  ;look for control char
		BCS     SW_PRT_LINE_X   ;none, so abort
		PSHX                    ;save address of cntrl char
		BEQ     DO_CNTRL_CHAR   ;if no printable chars, then skip
		PSHB                    ;save # chars to print
		LDAB    COLUMN_NUMBER   ;get # spaces to print
		JSR     PRINT_N_SPACES  ;print them
		LDX     BUF2_EMPTY_PTR  ;$0112 - get buffer empty ptr
		CLI                     ;enable ints
		PULB                    ;restore # of chars to print
		INCB                    ;setup for loop dec
SW_FWD_LOOP     DECB                    ;dec count
		BEQ     SW_LINE_CR      ;skip when B=0
		PSHB                    ;save count
		JSR     SERIAL_PRINTER  ;print byte at X
		PULB                    ;restore count
		DEC     BUF_2_COUNT     ;$0114 - dec the real buffer count
		INC     COLUMN_NUMBER   ;inc the column number
		JSR     BUMP_PBUF       ;inc the buffer ptr in X
		BRA     SW_FWD_LOOP     ;loop until done
SW_LINE_CR      JSR     PRINT_CR        ;print a CR

;... fall through

DO_CNTRL_CHAR   SEI                      ;diable ints
		LDAB    DEV2D_STATUS     ;$00FE - get status
		PULX                     ;restore cntrl char ptr
		STX     BUF2_EMPTY_PTR   ;$0112 - save as new buf empty ptr
		LDAA    $0000,X          ;get char from buffer
		BEQ     GOT_NULL         ;if it's a NULL, skip
		CMPA    #$000B           ;is it VT, 1/2 LF?
		BEQ     GOT_VTAB         ;yes-skip
		CMPA    #$0008           ;is it BS Backspace?
		BEQ     GOT_BS           ;yes-skip
		CMPA    #$000E           ;is it SO, reverse printer?
		BEQ     GOT_SO           ;yup, skip
		CMPA    #$000F           ;is it SI, cancel reverse printing?
		BEQ     GOT_SI           ;yes-skip
		CMPA    #$000D           ;CR carraige return?
		BEQ     GOT_CR            ;skip
		CMPA    #$000A           ;LF line feed?
		BEQ     GOT_LF            ;skip

;here if char is 0 or anything other than the above

GOT_NULL
		ANDB    ~(#SW_GOT_VTAB+#SW_GOT_BS)  ;#$00FC reset bits 0 and 1
		BRA     DONE_BUF_CHR

SW_PRT_LINE_X   RTS                      ;exit

;here if char is Line Feed

GOT_LF          PSHX                      ;save empty ptr
		LDAA    #$000A            ;line feed
		LDX     BUF2_FILL_PTR     ;$0110 - get fill ptr
		STAA    $0000,X           ;store char there
		JSR     SERIAL_PRINTER    ;print it
		PULX                      ;restore empty ptr
		SEI                       ;disable ints
		LDAB    DEV2D_STATUS      ;$00FE - get printer status
		ANDB    ~(#SW_GOT_VTAB+#SW_GOT_BS)  ;#$00FC reset bits 0 and 1
		BRA     DONE_BUF_CHR

;here if char is CR

GOT_CR          LDAA    #$0001            ;set column to 1
		STAA    COLUMN_NUMBER

GOT_SI          ANDB    ~(#SW_REV_ON+#SW_GOT_VTAB+#SW_GOT_BS) ;#$007C reset bits 7,1,0
		BRA     DONE_BUF_CHR

GOT_BS          ORAB    #SW_GOT_BS        ;#$0002 set bit 1
		ANDB    ~#SW_GOT_VTAB     ;#$00FE reset bit 0
		BRA     DONE_BUF_CHR

GOT_VTAB        ORAB    #SW_GOT_VTAB      ;#$0001 set bit 0
		ANDB    ~#SW_GOT_BS       ;#$00FD reset bit 1
		BRA     DONE_BUF_CHR

GOT_SO          INC     COLUMN_NUMBER     ;inc column number
		ORAB    #SW_REV_ON        ;#$0080 - set reverse on bit
		ANDB    ~(#SW_GOT_VTAB+#SW_GOT_BS)  ;#$00FC reset bits 0 and 1

;...fall through

;***********************************************************************
;* DONE_BUF_CHR
;*      X has buffer to inc and store
;*      B has new status to save
;***********************************************************************

DONE_BUF_CHR    JSR     BUMP_PBUF       ;inc printer buffer in X
		STX     BUF2_EMPTY_PTR  ;$0112 - store new empty ptr
		DEC     BUF_2_COUNT     ;$0114 - dec the buffer count
DONE_NO_BUF     STAB    DEV2D_STATUS    ;$00FE - store new printer status
		CLI                     ;enable ints
		RTS

;***********************************************************************
;* SW_REVERSE
;***********************************************************************

SW_REVERSE      JSR     SCAN_FOR_CNTRL  ;scan for control char
		BCS     SW_PRT_LINE_X   ;exit if one not found
		PSHX                    ;save address of control char
		BEQ     DO_CNTRL_CHAR   ;if B=0 then just go do cntrl
		PSHB                    ;else, save # of chars to print
		LDAA    COLUMN_NUMBER   ;get column number
		SBA                     ;column = last column - # chars
		TAB                     ;get # spaces in B
		DECA                    ;get real column number ???
		STAA    COLUMN_NUMBER
		JSR     PRINT_N_SPACES  ;print # of spaces
		CLI                     ;enable ints
		PULB                    ;restore # of chars to print
		INCB                    inc it to prepare for loop dec
		PULX                    ;restore cntrl char address
		PSHX                    ;save it again
		DEX                     ;point to last printable char
SW_REV_LOOP     DECB                    ;dec count
		BEQ     SW_REVLINE_DONE ;skip when B=0
		PSHB                    ;save count
		JSR     SERIAL_PRINTER  ;print the char at X
		PULB                    ;restore count
		DEC     BUF_2_COUNT     ;$0114 - dec the real buffer count
		DEX                     ;dec the buffer ptr
		CPX     #BUFFER_2 - #1  ;#$0115 - stay in buffer!
		BNE     SW_REV_LOOP     ;loop if OK
		LDX     #BUF_2_END - #1 ;#$01C0 - make it end of buffer
		BRA     SW_REV_LOOP     ;loop till done
SW_REVLINE_DONE JMP     SW_LINE_CR      ;do end process

;********************************************************************
;* Scan_for_control - scan the printer buffer for a control character
;* If one is found, return with the Carry reset, and the number of
;* chars preceeding it in B, X = address of control char found
;* Else, return with the Carry set.
;********************************************************************

SCAN_FOR_CNTRL  LDX     BUF2_EMPTY_PTR  ;$0112 - get the buf empty ptr
		LDAB    BUF_2_COUNT     ;$0114 - and the buffer count
		CLR     TMP_PARITY      ;$00F8 - clear # chars printed
PRT_BUF_LOOP    LDAA    $0000,X         ;get char from buffer
		CMPA    #' '            ;#$0020 is it below a space?
		BMI     PRT_BUF_ERR     ;yup, skip
		INC     TMP_PARITY      ;$00F8 - inc # chars "printed"
		JSR     BUMP_PBUF       ;bump the buffer ptr in X
		DECB                    ;decrement chars in buffer
		BNE     PRT_BUF_LOOP    ;loop until b=0
		SEI                     ;disable ints
		LDAA    DEV2D_STATUS    ;$00FE
		ANDA    ~#SW_BYTE_AVAIL ;#$00BF reset bit 6
		STAA    DEV2D_STATUS    ;$00FE
		CLI                     ;enable ints
		SEC                     ;set carry
		RTS

PRT_BUF_ERR     LDAB    TMP_PARITY      ;$00F8 - get # chars printed?
		CLC                     ;clear carry
		RTS

;************************************************************************
;* Process parallel characters
;************************************************************************

DO_PARALLEL     LDAA    PAR_DISABLE     ;$0115
		CMPA    #$00FF          ;disabled?
		BNE     PAR_NOT_DIS     ;no-skip
		LDAA    PAR_XMIT_BUF    ;$00FF - get parallel char to print
		CMPA    #$00E2          ;special char?
		BNE     NOT_E2          ;no, skip
		BRA     RESET_PP_AVAIL  ;yes-swallow it

NOT_E2          CMPA    #$00FE          ;special char?
		BEQ     RESET_PP_AVAIL  ;yes-skip it

		LDAA    #$000C          ;Form Feed
		LDX     BUF2_FILL_PTR   ;$0110 - store it in buffer
		STAA    $0000,X
		JSR     ParallelPrinter ;print it
		LDAA    #$0000          ;enable parallel printer again
		STAA    PAR_DISABLE     ;$0115

PAR_NOT_DIS     LDX     BUF2_FILL_PTR   ;$0110
		LDAA    PAR_XMIT_BUF    ;$00FF - get parallel char
		CMPA    #$0008          ;is it BS?
		BEQ     GOT_P_BS        ;LFB68 yes-skip

		CMPA    #$00E2          ;special char?
		BNE     NOT_E2_2        ;no-skip
		LDAA    #$00FF          ;disable parallel printer
		STAA    PAR_DISABLE     ;$0115
		BRA     RESET_PP_AVAIL  ;trash the byte

GOT_P_BS        ;LFB68
		LDX     BUF2_FILL_PTR     ;$0110 - get fill ptr
		LDAA    #$000D            ;store CR there
		STAA    $0000,X
		JSR     ParallelPrinter   ;print it
		LDX     BUF2_FILL_PTR     ;$0110 - get fill ptr
		LDAA    #$0020            ;prepare space

NOT_E2_2        STAA    $0000,X           ;stash byte at fill ptr
		JSR     ParallelPrinter   ;print it

RESET_PP_AVAIL  SEI                       ;disable ints
		LDAA    DEV2D_STATUS      ;$00FE
		ANDA    ~#PP_BYTE_AVAIL   ;#$00EF reset bit 4
		STAA    DEV2D_STATUS      ;$00FE
		CLI                       ;enable ints
		RTS

;*****************************************************************
;* Serial Printer
;*****************************************************************

SERIAL_PRINTER  LDAA    P1_DATA                 ;$0002 - get switch bits
		BITA    #$0040                  ;is bit 6 on?
		BNE     ParallelPrinter         ;yes-skip
SP_STATE_LOOP   LDAA    CUR_E_STATE             ;$00F4 - no, get serial state
		BNE     SP_STATE_LOOP           ;loop until it's 0
		LDAA    RAM_STAT_MSG_E+5        ;$00F2 - get serial status
		PSHA                            ;save it
		ORAA    #SS_BYTE_AVAIL          ;#$0002 - set byte ready
		STAA    RAM_STAT_MSG_E+5        ;$00F2 - save new status
		LDAA    U_XMIT_BUF              ;$00F3 - get cur serial byte
		PSHA                            ;save it
		LDAA    $0000,X                 ;get printer byte
		STAA    U_XMIT_BUF              ;$00F3 - save it as serial in
SP_DONE_LOOP    CLI                             ;enable ints
		JSR     SEND_UART_DATA          ;go send the data out RS232
		LDAA    RAM_STAT_MSG_E+5        ;$00F2 - get status
		BITA    #SS_BYTE_AVAIL          ;#$0002 - is the byte gone?
		BNE     SP_DONE_LOOP            ;no-loop until it is
		PULA                            ;restore the original
		STAA    U_XMIT_BUF              ;$00F3 - incoming byte
		PULA                            ;and the original status
		STAA    RAM_STAT_MSG_E+5        ;$00F2
		CLI                             ;enable ints
		RTS

;***********************************************************************
;* ParallelPrinter
;***********************************************************************

ParallelPrinter CLI                             ;enable ints
		LDAB    P1_DATA                 ;$0002 - get switch bits
		BITB    #$0010                  ;is bit 4 set?
		BNE     ParallelPrinter         ;no-loop until it is (BUSY?)
		BITB    #$0008                  ;is bit 3 set? (PAPER OUT?)
		BEQ     ParallelPrinter         ;no-loop until it is (SELECT?)
		SEI                             ;disable ints
		LDAA    $0000,X                 ;get char from buffer and
						;latch into parallel chip
		ORAB    #$0001                  ;set DataStrobe bit
		STAB    P1_DATA                 ;Strobe printer
		ANDB    #$00FE                  ;reset strobe bit
		STAB    P1_DATA
		CLI                             ;enable ints
		RTS

;**************************************************
;* PRINT_N_SPACES - number of spaces+1 to print in B
;**************************************************

PRINT_N_SPACES  LDX     BUF2_FILL_PTR           ;$0110 - get fill ptr
		LDAA    #$0020                  ;stuff SPACE there
		STAA    $0000,X
DEC_PRINT_CNT   DECB                            ;dec count
		BNE     PRINT_N_CHARS           ;print one
		RTS                             ;done

PRINT_N_CHARS   PSHB                            ;save count
		JSR     SERIAL_PRINTER          ;print char
		PULB                            ;restore count
		BRA     DEC_PRINT_CNT           ;loop if more

;************************************
;* PRINT_CR
;************************************

PRINT_CR        LDX     BUF2_FILL_PTR           ;$0110 - get fill ptr
		LDAA    #$000D                  ;Stuff CR there
		STAA    $0000,X
		JMP     SERIAL_PRINTER          ;print it

;*************************************************************************
;* BUMP_PBUF - increments the printer buffer, wrapping to the top
;*             if needed
;*************************************************************************

BUMP_PBUF       INX                             ;inc IX buffer ptr
		CPX     #BUF_2_END              ;at end?
		BNE     PBUF_NO_WRAP            ;no-skip
		LDX     #BUFFER_2               ;#$0116 - reset ptr to top
PBUF_NO_WRAP    RTS

;****************************************************************
;* MAC - This routine is called whenever a serial byte is
;*       received from the network.
;****************************************************************

SPI_MAC         equ     $               ;Serial interrupt routine
		LDAB    SCI_TR_CS       ;$0011 get serial status in B
		LDAA    SCI_RX          ;$0012 get serial data in A
		ANDB    #ORFE           ;$0040 framing error?
		BNE     NOT_FOR_US      ;yup-skip
		LDAB    #$000A          ;turn off the rx interrupt
		STAB    SCI_TR_CS       ;$0011

		LDAB    CUR_E_STATE      ;$00F4
		BNE     DO_STATE         ;if state != CNTRL then skip

		LDAB    CUR_2_STATE      ;$00F6
		BNE     DO_STATE

		LDAB    CUR_D_STATE      ;$00F5
		BNE     DO_STATE

		TAB                     ;get data in B
		ANDB    #$000F          ;isolate net address
		CMPB    #E_ADDRESS      ;$000E
		BEQ     CONTROL_E
		CMPB    #2_ADDRESS      ;$0002
		BNE     NOT_CONTROL_2
		JMP     CONTROL_2

NOT_CONTROL_2   CMPB    #D_ADDRESS    ;$000D
		BEQ     CONTROL_D

NOT_FOR_US      LDAB    #$001B           ;set wakeup bit
		STAB    SCI_TR_CS        ;$0011
		LDAA    #CNTRL           ;$0000 back to command mode
		STAA    CUR_E_STATE      ;$00F4
		STAA    CUR_2_STATE      ;$00F6
		STAA    CUR_D_STATE      ;$00F5
		RTI

;***************************************************************************
;* DO_STATE - we get here if one of the 3 state variables is not 0
;*            Network data is in A
;*            State # is in B
;***************************************************************************

DO_STATE        ASLB                    ;State * 2 for table lookup
		LDX     #JMPTBL         ;Jump Table to process current state
		ABX                     ;index into table
		LDX     $0000,X         ;get routine address
		JMP     $0000,X         ;jump to it

JMPTBL  equ     $

;RS232 states (device $0E)

		dw      CONTROL_E       ;$00
		dw      GET_LEN_H       ;$01
		dw      GET_LEN_L       ;$02
		dw      GET_DATA        ;$03
		dw      GET_CS          ;$04
		dw      GET_COMMAND     ;$05
		dw      GET_CMD_DATA    ;$06

;Centronics states (device $0D)

		dw      GET_LEN_H_D     ;$07
		dw      GET_LEN_L_D     ;$08
		dw      GET_DATA_D      ;$09
		dw      GET_CS_D        ;$0A

;SmartWriter intercept states (device $02)

		dw      GET_LEN_H_2     ;$0B
		dw      GET_LEN_L_2     ;$0C
		dw      GET_DATA_2      ;$0D
		dw      GET_CS_2        ;$0E

;********************************************************
;* Control State
;********************************************************

CONTROL_E       CMPA    #MN_STATUS+E_ADDRESS      ;$001E
		BNE     NOT_E_STATUS
		JMP     STATUS_E                  ;LFD44, clobbered

NOT_E_STATUS    CMPA    #MN_CLR+E_ADDRESS         ;$003E
		BNE     NOT_E_CLR
		JMP     DO_CLR_E

NOT_E_CLR       CMPA    #MN_READY+E_ADDRESS       ;$00DE
		BNE     NOT_E_READY
		JMP     READY_E

NOT_E_READY     CMPA    #MN_RECEIVE+E_ADDRESS     ;$004E
		BNE     NOT_E_RECEIVE
		JMP     DO_RCV

NOT_E_RECEIVE   CMPA    #MN_SEND+E_ADDRESS        ;$006E
		BNE     NOT_E_SEND
		JMP     SEND_E

NOT_E_SEND      CMPA    #MN_RESET+E_ADDRESS       ;$000E
		BNE     NOT_RESET
		JMP     RESET_E

;**********************************************************

CONTROL_D       CMPA    #MN_READY+D_ADDRESS       ;$00DD
		BNE     NOT_D_READY
		JMP     READY_D

NOT_D_READY     CMPA    #MN_STATUS+D_ADDRESS      ;$001D
		BNE     NOT_D_STATUS
		JMP     STATUS_D                  ;LFD36, clobbered

NOT_D_STATUS    CMPA    #MN_SEND+D_ADDRESS        ;$006D
		BNE     NOT_D_SEND
		JMP     SEND_D

NOT_D_SEND      CMPA    #MN_RECEIVE+D_ADDRESS     ;$004D
		BNE     NOT_D_RCV
		JMP     SEND_NACK_D

NOT_D_RCV       CMPA    #MN_CLR+D_ADDRESS         ;$003D
		BNE     NOT_D_CLR
		JMP     SEND_NACK_D

NOT_D_CLR       CMPA    #MN_RESET+D_ADDRESS       ;$000D
		BNE     NOT_RESET
		JMP     RESET_D

NOT_RESET       JMP     NOT_FOR_US

;******************************************************************

CONTROL_2       LDAB    P1_DATA         ;$0002
		BITB    #$0080
		BEQ     NOT_RESET

		CMPA    #MN_READY+2_ADDRESS       ;$00D2
		BNE     NOT_2_READY
		JMP     READY_2

NOT_2_READY     CMPA    #MN_STATUS+2_ADDRESS      ;$0012
		BNE     NOT_2_STATUS
		JMP     STATUS_2                  ;LFD3D, clobbered

NOT_2_STATUS    CMPA    #MN_RECEIVE+2_ADDRESS     ;$0042
		BNE     NOT_2_RCV
		JMP     SEND_NACK_2

NOT_2_RCV       CMPA    #MN_CLR+2_ADDRESS         ;$0032
		BNE     NOT_2_CLR
		JMP     SEND_NACK_2

NOT_2_CLR       CMPA    #MN_SEND+2_ADDRESS        ;$0062
		BNE     NOT_2_SEND
		JMP     SEND_2

NOT_2_SEND      CMPA    #MN_RESET+2_ADDRESS       ;$0002
		BNE     NOT_RESET
		BRA     RESET_2

;***************************************************************
;* RESET
;***************************************************************

RESET_E         LDX     #BUFFER                 ;#$008D - init buffer ptrs
		STX     BUF_FILL_PTR            ;$0087
		STX     BUF_EMPTY_PTR           ;$0089
		CLR     RAM_STAT_MSG_E+5        ;$00F2 - wipe out status
		CLR     BUF_COUNT               ;$008C - and buf count
		JMP     JUST_RETURN

RESET_D         LDAA    DEV2D_STATUS            ;$00FE - get status
		ANDA    ~#PP_BYTE_AVAIL         ;#$00EF reset bit 4
		BRA     RESET_D2_COMN

RESET_2         LDX     #BUFFER_2               ;#$0116
		STX     BUF2_FILL_PTR           ;$0110 - reset buffers
		CLR     BUF_2_COUNT             ;$0114
		LDAA    DEV2D_STATUS            ;$00FE - get status
		ANDA    ~(#SW_REV_ON+#SW_BYTE_AVAIL+
			#$20+#SW_GOT_BS+#SW_GOT_VTAB) ;#$001C reset bits 7,6,5,1,0

RESET_D2_COMN   STAA    DEV2D_STATUS            ;$00FE - save status
		JMP     JUST_RETURN

;********************************************************
;* RECEIVE state for RS232
;********************************************************

DO_RCV          LDAA    BUF_COUNT       ;$008C
		BEQ     DO_RCV_NACK     ;nothing to send, do error
		JMP     SEND_ACK_E      ;tell master we are ready

DO_RCV_NACK     JMP     SEND_NACK_E

;********************************************************
;* SEND
;* Prepare for incoming message
;********************************************************

SEND_E          LDAA    #LENGTH_HI       ;$0001-set up next state
		STAA    CUR_E_STATE      ;$00F4
		JMP     JUST_RETURN

SEND_D          LDAA    #LENGTH_HI_D     ;#$0007 - set up next state
		STAA    CUR_D_STATE      ;$00F5
		JMP     JUST_RETURN

SEND_2          LDAA    #LENGTH_HI_2     ;#$000B - set up next state
		STAA    CUR_2_STATE      ;$00F6
		JMP     JUST_RETURN

;********************************************************
;* READY
;* ACK or NACK our ready status
;********************************************************

READY_E         LDAA    RAM_STAT_MSG_E+5     ;$00F2-get status msg
		BITA    #SS_BYTE_AVAIL       ;#$0002 are we busy?
		BNE     SEND_NACK_E          ;yes, go NACK
		JMP     SEND_ACK_E           ;nope, we are OK, send ACK

READY_2         LDAA    DEV2D_STATUS         ;$00FE - get status
		BITA    #SW_BYTE_AVAIL       ;#$0040 bit 6 set, we are busy
		BNE     RDY_2_NACK           ;so go NACK
		JMP     SEND_ACK_2

RDY_2_NACK      JMP     SEND_NACK_2

READY_D         LDAA    DEV2D_STATUS         ;$00FE - get status
		BITA    #PP_BYTE_AVAIL       ;#$0010 bit 4 set?
		BEQ     SEND_ACK_D           ;no-we're OK
		JMP     SEND_NACK_D          ;yes, we're busy

;***********************************************************************
;* STATUS
;* These routines got clobbered with the last 59 bytes of the binary,
;* represented by the interrupt vector table and some of the FF filler.
;***********************************************************************

STATUS_D
LFD36
		dw      $FFFF,$FFFF,$FFFF
		db      $FF

;       xxxx    LDAA    #statout        ;
;       xxxx    STAA    CUR_D_STATE     ;$00F5
;       xxxxxx  JMP     $xxxx           ;

STATUS_2
LFD3D
		dw      $FFFF,$FFFF,$FFFF
		db      $FF

;       xxxx    LDAA    #statout        ;
;       xxxx    STAA    CUR_2_STATE     ;$00F6
;       7Exxxx  JMP     $xxxx           ;

STATUS_E
LFD44
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF

;       xxxx    LDAA    #statout        ;
;       xxxx    STAA    CUR_E_STATE     ;$00F4
;       xxxx    LDAA    #$0F            ;RDRF off, TDRE on, wakeup=1
;       xxxx    STAA    SCI_TR_CS       ;$0011
;       xxxx    LDAA    #tdre_int
;       xxxx    STAA    int_flag

LFD50
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FBED                   ;SPI_MAC
		dw      $F800                   ;START
		dw      $F800                   ;START
		dw      $F800                   ;START
		dw      $F800                   ;START
		dw      $F800                   ;START
		dw      $F800                   ;START
		dw      $F800                   ;START  the 00 is at A_FD6F
		db      $DF

;       xxxxxx  LDX     stat_pkt_size-1
;       xxxx    STX     COUNT
;       xxxx    LDAA    #$0001
;       xxxx    STAA    data_index
;       xxxxxx  CLR     CS_BYTE
;       xxxxxx  LDAA    RAM_STAT_MSG_E
;       xxxx    STAA    SCI_TX
;       xxxxxx  JMP     JUST_RETURN

;       xxxx
;       xxxx
;       xxxx
;       xxxx
;       xxxx
;       xxxx
;       xxxx
;       xxxx

;       ??DF    B??     LFD50           ;possible conditional branch?
					;the only other place $DF appears as
					;an argument is as a value to force
					;RTS high in GET_RTS.  Instructions
					;which begin on an address of the
					;form $xxDF appear to be unrelated
					;to the logic, hence I don't think
					;it's part of a JMP $xxDF or
					;JSR $xxDF.

		JMP     JUST_RETURN     ;7EFE24 in binary

;********************************************************
;* ACK and NACK
;* actually send the ACKs and NACKs
;********************************************************

SEND_NACK_2     ;LFD74
		LDAA    #NM_NACK+2_ADDRESS      ;$00C2
		BRA     SEND_REPLY

SEND_NACK_D     LDAA    #NM_NACK+D_ADDRESS      ;$00CD
		BRA     SEND_REPLY

SEND_NACK_E     LDAA    #NM_NACK+E_ADDRESS      ;$00CE
		BRA     SEND_REPLY

SEND_ACK_2      LDAA    #NM_ACK+2_ADDRESS       ;$0092
		BRA     SEND_REPLY

SEND_ACK_D      LDAA    #NM_ACK+D_ADDRESS       ;$009D
		BRA     SEND_REPLY

SEND_ACK_E      LDAA    #NM_ACK+E_ADDRESS       ;$009E

SEND_REPLY      JSR     NET_XMIT
		JSR     XMIT_CU
		JMP     JUST_RETURN

;***********************************************************
;* CLR_E state - send data
;***********************************************************

DO_CLR_E        LDAA    BUF_COUNT       ;$008C
		BEQ     SEND_NACK_E     ;nothing to send!

		LDAA    CHAR_MODE_FLAG  ;if this is 1 then send 1 byte
		BEQ     CLR_MORE_THAN_1 ;else go send multiple bytes

		LDX     BUF_EMPTY_PTR           ;$0089 get ptr to data
		LDD     #$0001                  ;send 1 byte
		STD     COUNT                   ;0E7H
		JSR     LETS_SEND_DATA
		BCS     CLR_EXIT

		LDX     BUF_EMPTY_PTR           ;$0089
		INX                             ;inc buffer pointer
		CPX     #BUF_END                ;#$00E7
		BNE     CLR_BUF_OK
		LDX     #BUFFER                 ;reset ptr to buffer start

CLR_BUF_OK      STX     BUF_EMPTY_PTR           ;$0089 - save new ptr
		DEC     BUF_COUNT               ;$008C - dec buffer count
CLR_EXIT        JMP     JUST_RETURN

;alt send routine sends multiple bytes directly from buffer.

CLR_MORE_THAN_1 LDX     BUF_EMPTY_PTR          ;$0089
		LDAB    RAM_STAT_MSG_E+4       ;$00F1 - get xmit size
		ANDB    #$003F                 ;make sure we send < 64 bytes
		CLRA                           ;zero out high byte
		STD     COUNT                  ;0E7H - store word
		JSR     LETS_SEND_DATA
		JMP     JUST_RETURN

;*******************************************************************
;* LETS_SEND_DATA - subroutine to dump data out onto the net
;*******************************************************************

;Assumes pointer in X, bytes to xmit in COUNT, COUNT+1

LETS_SEND_DATA  LDAA    #NM_SEND+E_ADDRESS      ;$00BE send command
		JSR     NET_XMIT
		LDAA    COUNT                   ;0E7H  and count
		JSR     NET_XMIT
		LDAA    COUNT+1                 ;0E8H
		JSR     NET_XMIT
		CLR     CS_BYTE                 ;$00E9 clear the checksum

		LDAA    CHAR_MODE_FLAG          ;if 0 then update buffer ptrs
		BEQ     LSD_LOOP_2              ;go dump from buffer (w/update)

;this loop just sends COUNT bytes of data from X without updating
;the buffer pointer.

LSD_LOOP_1      LDAA    $0000,X                 ;get the byte
		JSR     NET_XMIT
		EORA    CS_BYTE     ;$00E9
		STAA    CS_BYTE     ;$00E9
		INX
		LDD     COUNT       ;0E7H       ;sub 1 from count
		SUBD    #$0001
		STD     COUNT       ;0E7H       ;save it
		BNE     LSD_LOOP_1              ;and loop if there's more

		LDAA    CS_BYTE     ;$00E9
		JSR     NET_XMIT                ;send the cs
		JSR     XMIT_CU                 ;clean up
		RTS                             ;all done

;this loop sends data from serial buffer and updates the buffer pointer
;and buffer count.  X should be pointing to a buffer location.

LSD_LOOP_2      LDAA    $0000,X                 ;get the byte
		JSR     NET_XMIT
		EORA    CS_BYTE     ;$00E9
		STAA    CS_BYTE     ;$00E9
		INX
		DEC     BUF_COUNT   ;$008C      ;decrement buffer count
		CPX     #BUF_END                ;at end of buffer?
		BNE     LSD_BUF_OK              ;no-skip
		LDX     #BUFFER     ;#$008D     ;else reset buf ptr

LSD_BUF_OK      LDD     COUNT      ;0E7H        ;sub 1 from count
		SUBD    #$0001
		STD     COUNT      ;0E7H
		BNE     LSD_LOOP_2              ;and loop if more to do

		STX     BUF_EMPTY_PTR  ;$0089   ;save new buffer ptr
		LDAA    CS_BYTE        ;$00E9
		JSR     NET_XMIT                ;send checksum
		JSR     XMIT_CU                 ;clean up
		RTS                             ;done

;*****************************************************************
;* JUST_RETURN
;*****************************************************************

JUST_RETURN     LDAA    SCI_TR_CS       ;$0011 read status
		ORAA    #$0010          ;turn on receive interrupt
		STAA    SCI_TR_CS       ;$0011
		LDAA    SCI_RX          ;$0012 read data (trash)
		RTI

;***********************************************
;* Get length hi state - byte in A
;***********************************************

GET_LEN_H                                ;LFE2D
		STAA    COUNT            ;0E7H  - store hi length
		LDAA    #LENGTH_LO       ;$0002 - set up for next state
		STAA    CUR_E_STATE      ;$00F4
		JMP     JUST_RETURN

GET_LEN_H_D     STAA    COUNT            ;0E7H   - save hi length
		LDAA    #LENGTH_LO_D     ;#$0008 - set up next state
		STAA    CUR_D_STATE      ;$00F5
		JMP     JUST_RETURN

GET_LEN_H_2     STAA    COUNT            ;0E7H   - save hi length
		LDAA    #LENGTH_LO_2     ;#$000C - set up next state
		STAA    CUR_2_STATE      ;$00F6
		JMP     JUST_RETURN

;************************************************
;* Get length low state
;************************************************

GET_LEN_L       STAA    COUNT+1         ;0E8H - save low count
		CMPA    #$0002          ;2 byte message coming
		BEQ     A_2_BYTE_MSG    ;yes-it's a UART command-skip
		LDAA    #DATAIN         ;no-set up for data state
		STAA    CUR_E_STATE     ;$00F4
		JMP     JUST_RETURN

A_2_BYTE_MSG    LDAA    #CMD_IN          ;$0005 - set up to get UART command
		STAA    CUR_E_STATE      ;$00F4
		JMP     JUST_RETURN

GET_LEN_L_D     STAA    COUNT+1          ;0E8H - save low count
		CLRA
		LDAA    #DATAIN_D        ;#$0009 - set up for next state
		STAA    CUR_D_STATE      ;$00F5
		JMP     JUST_RETURN

GET_LEN_L_2     STAA    COUNT+1         ;0E8H  - save low count
		CLR     CS_BYTE         ;$00E9 - init checksum
		CLR     TMP_COUNT       ;$00EA - init bytes received
		CLR     $00EB           ;??? bogus ???
		LDX     BUF2_FILL_PTR   ;$0110 - save current fill ptr in
		STX     SAV_BUF_PTR     ;$00F9 - case we need to restore it
		LDAA    #DATAIN_2
		STAA    CUR_2_STATE     ;$00F6 - set up for data state
		BRA     JUST_RETURN

;***********************************************************
;* Get data state
;***********************************************************

GET_DATA        STAA    U_XMIT_BUF       ;$00F3 - store data
		STAA    CS_BYTE          ;$00E9 - and check sum
		LDAA    #SS_BYTE_AVAIL   ;#$0002 signify data avail
		STAA    TMP_COUNT        ;$00EA
		LDAA    #CS_IN           ;#$0004 - set up for next state
		STAA    CUR_E_STATE      ;$00F4
		BRA     JUST_RETURN

GET_DATA_D      STAA    PAR_XMIT_BUF     ;$00FF - store char
		STAA    CS_BYTE          ;$00E9 - and checksum
		LDAA    #CS_IN_D         ;#$000A
		STAA    CUR_D_STATE      ;$00F5 - set up for next state
		BRA     JUST_RETURN

GET_DATA_2      LDX     BUF2_FILL_PTR   ;$0110 - get buffer 2 fill ptr
		STAA    $0000,X         ;store data in buffer
		EORA    CS_BYTE         ;$00E9 - update checksum
		STAA    CS_BYTE         ;$00E9
		INX                     ;inc buffer fill ptr
		CPX     #BUF_2_END      ;#$01C1 - at end of buffer?
		BNE     GD2_BUF_OK      ;no-skip
		LDX     #BUFFER_2       ;#$0116 - reset fill ptr to top

GD2_BUF_OK      STX     BUF2_FILL_PTR   ;$0110 - store new fill ptr
		INC     TMP_COUNT       ;$00EA - bump temp counter
		DEC     COUNT+1         ;0E8H - dec incoming count
		BNE     GD2_NOT_DONE    ;if not zero, stay in this state
		LDAA    CS_IN_2         ;#$000E - else setup for next state
		STAA    CUR_2_STATE     ;$00F6
GD2_NOT_DONE    JMP     JUST_RETURN

;**********************************************
;* Get check sum state - byte in A
;**********************************************

GET_CS          LDAB    #CNTRL                  ;$0000 - set up for next state
		STAB    CUR_E_STATE             ;$00F4
		CMPA    CS_BYTE                 ;$00E9 - checksums match?
		BNE     GCS_BAD_CS              ;nope-skip
		LDAA    RAM_STAT_MSG_E+5        ;$00F2 - yes, get status msg
		ORAA    TMP_COUNT               ;$00EA

;If this is data, then bit 2 will be set, signifying
;data is ready to send to the UART
;If this is a UART command, bit 1 will be set signifying
;a UART command is available to be processed

		STAA    RAM_STAT_MSG_E+5        ;$00F2 - save new status
		JMP     SEND_ACK_E
GCS_BAD_CS      JMP     SEND_NACK_E

GET_CS_D        LDAB    #CNTRL           ;$0000 - set up for next state
		STAB    CUR_D_STATE      ;$00F5
		CMPA    CS_BYTE          ;$00E9 - checksums match?
		BNE     GCS_D_BAD        ;no, go do NACK
		LDAA    DEV2D_STATUS     ;$00FE - get status
		ORAA    #PP_BYTE_AVAIL   ;#$0010 set bit 4
		STAA    DEV2D_STATUS     ;$00FE - save status
		JMP     SEND_ACK_D
GCS_D_BAD       JMP     SEND_NACK_D

GET_CS_2        LDAB    #CNTRL            ;$0000 - set up for next state
		STAB    CUR_2_STATE       ;$00F6
		CMPA    CS_BYTE           ;$00E9 - checksums match?
		BNE     GCS_2_BAD         ;no, restore fill ptr + do NACK
		LDAA    #NM_ACK+2_ADDRESS ;$0092
		JSR     NET_XMIT          ;send ACK
		JSR     XMIT_CU           ;clean up
		CLI                       ;allow ints
		LDAB    DEV2D_STATUS      ;$00FE - get status
		ORAB    #SW_BYTE_AVAIL    ;#$0040 set bit 6
		STAB    DEV2D_STATUS      ;$00FE - save status
		LDAA    BUF_2_COUNT       ;$0114 add count of stuff
		ADDA    TMP_COUNT         ;$00EA just received to
		STAA    BUF_2_COUNT       ;$0114 buffer count
		JMP     JUST_RETURN
GCS_2_BAD       LDX     SAV_BUF_PTR       ;$00F9 - restore the old fill ptr
		STX     BUF2_FILL_PTR     ;$0110
		JMP     SEND_NACK_2

;*********************************************************************
;* GET_COMMAND - gets a command byte which is actually an offset into
;*               the table at 0080H.
;*********************************************************************

GET_COMMAND     STAA    TMP_COUNT       ;$00EA  - save command
		STAA    CS_BYTE         ;$00E9  - and init checksum
		LDAA    #CMD_DATA_IN    ;#$0006 - setup next state
		STAA    CUR_E_STATE     ;$00F4
		JMP     JUST_RETURN

;******************************************************************
;* GET_CMD_DATA
;******************************************************************

GET_CMD_DATA    LDAB    TMP_COUNT     ;$00EA - retrieve the command
		LDX     #$0080        ;use it to index into table
		ABX
		STAA    $0000,X       ;store the data there

		EORA    CS_BYTE          ;$00E9 - add data to CS
		STAA    CS_BYTE          ;$00E9
		LDAA    #SS_CMD_AVAIL    ;#$0001 signify a command
		STAA    TMP_COUNT        ;$00EA - temp save til getCS
		LDAA    #CS_IN           ;$0004 - set up for CS in
		STAA    CUR_E_STATE      ;$00F4
		JMP     JUST_RETURN

;****************************************************
;* NET_XMIT
;****************************************************

NET_XMIT        LDAB    SCI_TR_CS     ;$0011  - get serial status
		ANDB    #TDRE_MASK    ;#$0020 - ready to send?
		BEQ     NET_XMIT      ;loop until it's ready
		STAA    SCI_TX        ;$0013 - send data

;...fall through

;****************************************************
;* HANG until tx busy???
;****************************************************

WAIT_TIL_TXBSY  LDAB    SCI_TR_CS      ;$0011  - get serial status
		ANDB    #TDRE_MASK     ;#$0020 - ready to send?
		BNE     WAIT_TIL_TXBSY ;loop until it's not ready
		SEC                    ;set carry
		RTS

;**********************************************************
;* This stuff duplicates XCU_ERR and XCU_ERR2, and isn't
;* called by anybody.  Maybe called by the STATUS routines
;* which got clobbered??
;**********************************************************

LFF3C
	LDAA    #0                      ;wipe out our status message
	STAA    RAM_STAT_MSG_E+5        ;$F2
	CLC                             ;clear CF (error)
	RTS

LFF42
	LDAA    #0                      ;wipe out our status message
	STAA    RAM_STAT_MSG_E+5        ;$F2
	CLC                             ;clear CF (error)
	RTS

;*********************************************************
;* Transmit cleanup, dump the byte we are receiving
;* that we just sent
;*********************************************************

XMIT_CU         LDX     #$0294         ;allow ? byte times
XCU_REPEAT      DEX                    ;dec timeout val
		BEQ     XCU_ERR        ;if 0 then error
		LDAB    SCI_TR_CS      ;$0011 - get serial status
		ANDB    #TDRE_MASK     ;#$0020 - transmit ready?
		BEQ     XCU_REPEAT     ;wait till xmit is done
		LDAB    SCI_RX         ;$0012 - get received data (??)

		LDX     #$0294         ;allow ? byte times
XCU_REPEAT2     DEX                    ;dec timeout value
		BEQ     XCU_ERR2       ;if 0 then error
		LDAB    SCI_TR_CS      ;$0011 - get serial status
		BPL     XCU_REPEAT2    ;wait until receiver full (bit7)
		LDAB    SCI_RX         ;$0012 - get received data
		SEC                    ;return success
		RTS

XCU_ERR         LDAA    #$0000                  ;wipe out our status msg
		STAA    RAM_STAT_MSG_E+5        ;$00F2
		CLC                             ;clear carry (error)
		RTS

XCU_ERR2        LDAA    #$0000                  ;wipe out our status msg
		STAA    RAM_STAT_MSG_E+5        ;$00F2
		CLC                             ;clear carry (error)
		RTS

STAT_MSG_TBL_E  equ     $                    ;MFF70
		db      $80+E_ADDRESS        ;$8E STATUS.OR.ADDRESS
		db      $10                  ;Max msg len (low byte)
		db      $00                  ;Max msg len (hi byte)
		db      $00                  ;xmit code - (bytes requested)
		db      $00                  ;status flags

STAT_MSG_TBL_2  EQU     $
		db      $80+2_ADDRESS        ;$82
		db      $10                  ;max msg len (lo)
		db      $00                  ;max msg len (hi)
		db      $00                  ;xmit code
		db      $00                  ;status flags

STAT_MSG_TBL_D  EQU     $
		db      $80+D_ADDRESS        ;$8D
		db      $01                  ;max msg len (lo)
		db      $00                  ;max msg len (hi)
		db      $00                  ;xmit code
		db      $00                  ;status flags

;*********************************************************************
;* Filler for unused space.
;*********************************************************************

		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		dw      $FFFF,$FFFF,$FFFF,$FFFF
		db      $FF

;******************************************************************
;* Interrupt vectors (absolute address $FFF0)
;******************************************************************

		dw      SPI_MAC         ;serial I/O interrupt
		dw      START
		dw      START
		dw      START
		dw      START
		dw      START
		dw      START
		dw      START

;******************************************************************
;* RAM locations
;******************************************************************

BAUD_RATE       EQU     $0080           ;see data sheet
CHAR_LEN        EQU     $0081           ;0=5,1=6,2=7,3=8
PARITY          EQU     $0082           ;0=E,1=O,2=N
STOP_BITS       EQU     $0083           ;0=1sb, 1=2sb
PROTOCOL        EQU     $0084           ;0=RTS/CTS, 1=XON/XOFF, 2=none
DTR_STATE       EQU     $0085           ;0=clr rx buf, 1=DTR on, 2=DTR off
CHAR_MODE_FLAG  EQU     $0086           ;0=multi byte net sends
					;1=single byte net sends

;********************************************************************
;* Serial port buffer
;********************************************************************

BUF_FILL_PTR    EQU     $0087           ;fill pointer for serial buffer
BUF_EMPTY_PTR   EQU     $0089           ;storage for buffer ptr
CMD_SHADOW      EQU     $008B           ;UART command register shadow
BUF_COUNT       EQU     $008C           ;# of items in buffer
BUFFER          EQU     $008D           ;start of serial buffer (89 bytes)
BUF_END         EQU     $00E7           ;end of the serial buffer define
BUF_SIZE        EQU     $005A           ;size of buffer define

COUNT           EQU     $00E7           ;word for # bytes to send master
CS_BYTE         EQU     $00E9           ;checksum

TMP_COUNT       EQU     $00EA           ;temp count for incoming data and
					;also used to set serial status
					;msg to data or cmd available

		EQU     $00EB           ;??? temp ??? bogus ???

RAM_STAT_MSG_E  EQU     $00ED           ;5 bytes for status message

U_XMIT_BUF      EQU     $00F3           ;holder for data to send to UART
CUR_E_STATE     EQU     $00F4
CUR_D_STATE     EQU     $00F5
CUR_2_STATE     EQU     $00F6

TMP_PARITY      EQU     $00F8           ;temp UART parity - # chars found
					;to be printed on line from
					;smartwriter buffer

SAV_BUF_PTR     EQU     $00F9           ;temp storage for buf 2 ptr so
					;it can be restored if the
					;network transfer that is filling
					;the buffer fails.

BS_COUNT        EQU     $00FC           ;backspace count
COLUMN_NUMBER   EQU     $00FD           ,phantom column number

DEV2D_STATUS    EQU     $00FE           ;status for both parallel and
					;SmartWriter printers
PAR_XMIT_BUF    EQU     $00FF           ;char to be sent out parallel port


;2651 UART is decoded at $0100-$010F

;This buffer is in both the memory and parallel port address space.
;The last access to this memory area will be latched into the
;parallel port chip, and may be output to the printer by toggling
;~DataStrobe low

BUF2_FILL_PTR   EQU     $0110           ;storage for buf 2 fill ptr
BUF2_EMPTY_PTR  EQU     $0112           ;ptr to data for printer to use
BUF_2_COUNT     EQU     $0114           ;# items in buffer
PAR_DISABLE     EQU     $0115           ;$FF here disables parallel output
					;until anything other than FE
					;or E2 appears at PAR_XMIT_BUF
					;E2 appearing at PAR_XMIT_BUF
					;causes FF to appear here.
BUFFER_2        EQU     $0116           ;start of buffer 2
BUF_2_END       EQU     $01C1           ;end of buffer 2 define (171 chars)

STACK           equ     $01FB

		end

;****************************************************************************
